package com.bank.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bank.dto.Result;
import com.bank.entity.CustomerCardView;
import com.bank.entity.TradeDetailView;
import com.bank.exception.BankException;
import com.bank.mapper.ViewMapper;
import com.bank.service.ViewService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 视图查询服务实现类
 * 提供对数据库视图的业务操作实现
 * 
 * @author 开发团队
 * @version 1.0.0
 * @since 2025-06-19
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class ViewServiceImpl implements ViewService {

    @Autowired
    private ViewMapper viewMapper;

    // ================================
    // 客户银行卡视图查询
    // ================================

    @Override
    @Transactional(readOnly = true)
    public Result<List<CustomerCardView>> getAllCustomerCards() {
        try {
            List<CustomerCardView> customerCards = viewMapper.selectAllCustomerCards();
            return Result.success(customerCards);
        } catch (Exception e) {
            log.error("查询所有客户银行卡视图数据异常：", e);
            throw new BankException("查询客户银行卡视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<IPage<CustomerCardView>> getCustomerCardsPage(Page<CustomerCardView> page,
                                                               String customerName,
                                                               String savingName,
                                                               String isReportLoss,
                                                               LocalDate startDate,
                                                               LocalDate endDate,
                                                               BigDecimal minBalance,
                                                               BigDecimal maxBalance) {
        try {
            if (startDate != null && endDate != null && startDate.isAfter(endDate)) {
                return Result.badRequest("开始日期不能晚于结束日期");
            }

            if (minBalance != null && maxBalance != null && minBalance.compareTo(maxBalance) > 0) {
                return Result.badRequest("最小余额不能大于最大余额");
            }

            IPage<CustomerCardView> result = viewMapper.selectCustomerCardsPage(page, customerName, savingName,
                    isReportLoss, startDate, endDate, minBalance, maxBalance);
            return Result.success(result);
        } catch (Exception e) {
            log.error("分页查询客户银行卡视图数据异常：", e);
            throw new BankException("查询客户银行卡视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<CustomerCardView>> getCustomerCardsByName(String customerName) {
        try {
            if (StringUtils.isBlank(customerName)) {
                return Result.badRequest("客户姓名不能为空");
            }

            List<CustomerCardView> customerCards = viewMapper.selectCustomerCardsByName(customerName);
            return Result.success(customerCards);
        } catch (Exception e) {
            log.error("根据客户姓名查询银行卡视图数据异常：", e);
            throw new BankException("查询客户银行卡视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<CustomerCardView>> getCustomerCardsBySavingType(String savingName) {
        try {
            if (StringUtils.isBlank(savingName)) {
                return Result.badRequest("存款类型不能为空");
            }

            List<CustomerCardView> customerCards = viewMapper.selectCustomerCardsBySavingType(savingName);
            return Result.success(customerCards);
        } catch (Exception e) {
            log.error("根据存款类型查询银行卡视图数据异常：", e);
            throw new BankException("查询客户银行卡视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<String> exportCustomerCardsToCSV() {
        try {
            List<CustomerCardView> customerCards = viewMapper.selectAllCustomerCards();

            StringBuilder csv = new StringBuilder();
            // CSV头部
            csv.append("卡号,客户姓名,身份证号,联系电话,存款类型,币种,开卡日期,开卡金额,账户余额,是否挂失,创建时间\n");

            // CSV数据
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            for (CustomerCardView card : customerCards) {
                csv.append(card.getCardId()).append(",")
                   .append(card.getCustomerName()).append(",")
                   .append(card.getPid()).append(",")
                   .append(card.getTelephone()).append(",")
                   .append(card.getSavingName()).append(",")
                   .append(card.getCurId()).append(",")
                   .append(card.getOpenDate() != null ? card.getOpenDate().format(dateFormatter) : "").append(",")
                   .append(card.getOpenMoney()).append(",")
                   .append(card.getBalance()).append(",")
                   .append(card.getIsReportLoss()).append(",")
                   .append(card.getCreateTime() != null ? card.getCreateTime().format(dateTimeFormatter) : "").append("\n");
            }

            return Result.success(csv.toString());
        } catch (Exception e) {
            log.error("导出客户银行卡视图数据到CSV异常：", e);
            throw new BankException("导出客户银行卡视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<String> exportCustomerCardsToCSV(String customerName,
                                                   String savingName,
                                                   String isReportLoss,
                                                   LocalDate startDate,
                                                   LocalDate endDate,
                                                   BigDecimal minBalance,
                                                   BigDecimal maxBalance) {
        try {
            // 参数验证
            if (startDate != null && endDate != null && startDate.isAfter(endDate)) {
                return Result.badRequest("开始日期不能晚于结束日期");
            }

            if (minBalance != null && maxBalance != null && minBalance.compareTo(maxBalance) > 0) {
                return Result.badRequest("最小余额不能大于最大余额");
            }

            // 获取过滤后的数据 - 使用分页查询但设置大页面大小来获取所有数据
            Page<CustomerCardView> page = new Page<>(1, Integer.MAX_VALUE);
            IPage<CustomerCardView> pageResult = viewMapper.selectCustomerCardsPage(page,
                    customerName, savingName, isReportLoss, startDate, endDate, minBalance, maxBalance);
            List<CustomerCardView> customerCards = pageResult.getRecords();

            StringBuilder csv = new StringBuilder();
            // CSV头部
            csv.append("卡号,客户姓名,身份证号,联系电话,存款类型,币种,开卡日期,开卡金额,账户余额,是否挂失,创建时间\n");

            // CSV数据
            DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            for (CustomerCardView card : customerCards) {
                csv.append(card.getCardId()).append(",")
                   .append(card.getCustomerName()).append(",")
                   .append(card.getPid()).append(",")
                   .append(card.getTelephone()).append(",")
                   .append(card.getSavingName()).append(",")
                   .append(card.getCurId()).append(",")
                   .append(card.getOpenDate() != null ? card.getOpenDate().format(dateFormatter) : "").append(",")
                   .append(card.getOpenMoney()).append(",")
                   .append(card.getBalance()).append(",")
                   .append(card.getIsReportLoss()).append(",")
                   .append(card.getCreateTime() != null ? card.getCreateTime().format(dateTimeFormatter) : "").append("\n");
            }

            return Result.success(csv.toString());
        } catch (Exception e) {
            log.error("导出客户银行卡视图数据到CSV异常：", e);
            throw new BankException("导出客户银行卡视图数据失败：" + e.getMessage());
        }
    }

    // ================================
    // 交易明细视图查询
    // ================================

    @Override
    @Transactional(readOnly = true)
    public Result<List<TradeDetailView>> getAllTradeDetails() {
        try {
            List<TradeDetailView> tradeDetails = viewMapper.selectAllTradeDetails();
            return Result.success(tradeDetails);
        } catch (Exception e) {
            log.error("查询所有交易明细视图数据异常：", e);
            throw new BankException("查询交易明细视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<IPage<TradeDetailView>> getTradeDetailsPage(Page<TradeDetailView> page,
                                                             String cardId,
                                                             String customerName,
                                                             String tradeType,
                                                             LocalDateTime startTime,
                                                             LocalDateTime endTime,
                                                             BigDecimal minAmount,
                                                             BigDecimal maxAmount) {
        try {
            if (startTime != null && endTime != null && startTime.isAfter(endTime)) {
                return Result.badRequest("开始时间不能晚于结束时间");
            }

            if (minAmount != null && maxAmount != null && minAmount.compareTo(maxAmount) > 0) {
                return Result.badRequest("最小金额不能大于最大金额");
            }

            IPage<TradeDetailView> result = viewMapper.selectTradeDetailsPage(page, cardId, customerName,
                    tradeType, startTime, endTime, minAmount, maxAmount);
            return Result.success(result);
        } catch (Exception e) {
            log.error("分页查询交易明细视图数据异常：", e);
            throw new BankException("查询交易明细视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<TradeDetailView>> getTradeDetailsByCardId(String cardId) {
        try {
            if (StringUtils.isBlank(cardId)) {
                return Result.badRequest("银行卡号不能为空");
            }

            List<TradeDetailView> tradeDetails = viewMapper.selectTradeDetailsByCardId(cardId);
            return Result.success(tradeDetails);
        } catch (Exception e) {
            log.error("根据卡号查询交易明细视图数据异常：", e);
            throw new BankException("查询交易明细视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<TradeDetailView>> getTradeDetailsByCustomerName(String customerName) {
        try {
            if (StringUtils.isBlank(customerName)) {
                return Result.badRequest("客户姓名不能为空");
            }

            List<TradeDetailView> tradeDetails = viewMapper.selectTradeDetailsByCustomerName(customerName);
            return Result.success(tradeDetails);
        } catch (Exception e) {
            log.error("根据客户姓名查询交易明细视图数据异常：", e);
            throw new BankException("查询交易明细视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<List<TradeDetailView>> getTradeDetailsByType(String tradeType) {
        try {
            if (StringUtils.isBlank(tradeType)) {
                return Result.badRequest("交易类型不能为空");
            }

            List<TradeDetailView> tradeDetails = viewMapper.selectTradeDetailsByType(tradeType);
            return Result.success(tradeDetails);
        } catch (Exception e) {
            log.error("根据交易类型查询交易明细视图数据异常：", e);
            throw new BankException("查询交易明细视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<String> exportTradeDetailsToCSV(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            List<TradeDetailView> tradeDetails;

            if (startTime != null && endTime != null) {
                if (startTime.isAfter(endTime)) {
                    return Result.badRequest("开始时间不能晚于结束时间");
                }
                // 这里可以添加按时间范围查询的方法，暂时使用全部数据然后过滤
                tradeDetails = viewMapper.selectAllTradeDetails();
                tradeDetails = tradeDetails.stream()
                        .filter(trade -> trade.getTradeDate().isAfter(startTime) && trade.getTradeDate().isBefore(endTime))
                        .collect(java.util.stream.Collectors.toList());
            } else {
                tradeDetails = viewMapper.selectAllTradeDetails();
            }

            StringBuilder csv = new StringBuilder();
            // CSV头部
            csv.append("交易ID,卡号,客户姓名,交易日期,交易类型,交易金额,目标卡号,备注,当前余额\n");

            // CSV数据
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            for (TradeDetailView trade : tradeDetails) {
                csv.append(trade.getTradeId()).append(",")
                   .append(trade.getCardId()).append(",")
                   .append(trade.getCustomerName()).append(",")
                   .append(trade.getTradeDate() != null ? trade.getTradeDate().format(dateTimeFormatter) : "").append(",")
                   .append(trade.getTradeType()).append(",")
                   .append(trade.getTradeMoney()).append(",")
                   .append(trade.getTargetCardId() != null ? trade.getTargetCardId() : "").append(",")
                   .append(trade.getRemark() != null ? trade.getRemark().replace(",", "，") : "").append(",")
                   .append(trade.getBalance()).append("\n");
            }

            return Result.success(csv.toString());
        } catch (Exception e) {
            log.error("导出交易明细视图数据到CSV异常：", e);
            throw new BankException("导出交易明细视图数据失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Result<String> exportTradeDetailsToCSV(String cardId,
                                                  String customerName,
                                                  String tradeType,
                                                  LocalDateTime startTime,
                                                  LocalDateTime endTime,
                                                  BigDecimal minAmount,
                                                  BigDecimal maxAmount) {
        try {
            // 参数验证
            if (startTime != null && endTime != null && startTime.isAfter(endTime)) {
                return Result.badRequest("开始时间不能晚于结束时间");
            }

            if (minAmount != null && maxAmount != null && minAmount.compareTo(maxAmount) > 0) {
                return Result.badRequest("最小金额不能大于最大金额");
            }

            // 获取过滤后的数据 - 使用分页查询但设置大页面大小来获取所有数据
            Page<TradeDetailView> page = new Page<>(1, Integer.MAX_VALUE);
            IPage<TradeDetailView> pageResult = viewMapper.selectTradeDetailsPage(page,
                    cardId, customerName, tradeType, startTime, endTime, minAmount, maxAmount);
            List<TradeDetailView> tradeDetails = pageResult.getRecords();

            StringBuilder csv = new StringBuilder();
            // CSV头部
            csv.append("交易ID,卡号,客户姓名,交易日期,交易类型,交易金额,目标卡号,备注,当前余额\n");

            // CSV数据
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

            for (TradeDetailView trade : tradeDetails) {
                csv.append(trade.getTradeId()).append(",")
                   .append(trade.getCardId()).append(",")
                   .append(trade.getCustomerName()).append(",")
                   .append(trade.getTradeDate() != null ? trade.getTradeDate().format(dateTimeFormatter) : "").append(",")
                   .append(trade.getTradeType()).append(",")
                   .append(trade.getTradeMoney()).append(",")
                   .append(trade.getTargetCardId() != null ? trade.getTargetCardId() : "").append(",")
                   .append(trade.getRemark() != null ? trade.getRemark().replace(",", "，") : "").append(",")
                   .append(trade.getBalance()).append("\n");
            }

            return Result.success(csv.toString());
        } catch (Exception e) {
            log.error("导出交易明细视图数据到CSV异常：", e);
            throw new BankException("导出交易明细视图数据失败：" + e.getMessage());
        }
    }
}
